# 引入数据集,sklearn包含众多数据集
import sklearn
import numpy as np
from sklearn.datasets import load_iris
#import sklearn
#from sklearn import datasets
# 将数据分为测试集和训练集
from sklearn.model_selection import train_test_split
# 利用邻近点方式训练数据
from sklearn.neighbors import KNeighborsClassifier
import matplotlib.pyplot as plt


def iris1():
    # 引入数据,本次导入鸢尾花数据,iris数据包含4个特征变量

    iris =  load_iris()
    # 特征变量
    iris_X = iris.data
    # print(iris_X)
    print('特征变量的长度', len(iris_X))
    # 目标值
    iris_y = iris.target
    print('鸢尾花的目标值', iris_y)
    # 利用train_test_split进行训练集和测试机进行分开,test_size占30%
    X_train, X_test, y_train, y_test = train_test_split(iris_X, iris_y, test_size=0.3)
    # 我们看到训练数据的特征值分为3类
    # print(y_train)
    '''
    [1 1 0 2 0 0 0 2 2 2 1 0 2 0 2 1 0 1 0 2 0 1 0 0 2 1 2 0 0 1 0 0 1 0 0 0 0
     2 2 2 1 1 1 2 0 2 0 1 1 1 1 2 2 1 2 2 2 0 2 2 2 0 1 0 1 0 0 1 2 2 2 1 1 1
     2 0 0 1 0 2 1 2 0 1 2 2 2 1 2 1 0 0 1 0 0 1 1 1 0 2 1 1 0 2 2]
     '''
    # 训练数据
    # 引入训练方法
    knn = KNeighborsClassifier()
    # 进行填充测试数据进行训练
    knn.fit(X_train, y_train)

    params = knn.get_params()
    print(params)
    '''
    {'algorithm': 'auto', 'leaf_size': 30, 'metric': 'minkowski',
     'metric_params': None, 'n_jobs': None, 'n_neighbors': 5,
     'p': 2, 'weights': 'uniform'}
    
    '''
    knn.fit(X_test, y_test)

    score = knn.score(X_test, y_test)
    print("预测得分为：%s" % score)
    '''
    预测得分为：0.9555555555555556
    [1 2 1 1 2 2 1 0 0 0 0 1 2 0 1 0 2 0 0 0 2 2 0 2 2 2 2 1 2 2 2 1 2 2 1 2 0
     2 1 2 1 1 0 2 1]
    [1 2 1 1 2 2 1 0 0 0 0 1 2 0 1 0 2 0 0 0 1 2 0 2 2 2 2 1 1 2 2 1 2 2 1 2 0
     2 1 2 1 1 0 2 1]
    '''

    # 预测数据,预测特征值
    print('预测数据,预测特征值')
    print(knn.predict(X_test))

    # 打印真实特征值
    print('打印真实特征值')
    print(y_test)


def digit1():
    from sklearn.datasets import load_digits
    import matplotlib.pyplot as plt

    digits = load_digits()
    print(digits.data.shape)
    print(digits.target.shape)
    print(digits.images.shape)



    from sklearn.datasets import load_digits

    plt.matshow(digits.images[0])
    plt.matshow(digits.images[100])
    plt.matshow(digits.images[500])
    plt.matshow(digits.images[1796])
    plt.show()

def make_cl1():
    """1.2
    创建数据集

    　　我们除了可以使用sklearn自带的数据集,还可以自己去创建训练样本,

    具体用法可以参考"""


    from sklearn.datasets.samples_generator import make_classification

    X, y = make_classification(n_samples=6, n_features=5, n_informative=2,
                               n_redundant=2, n_classes=2, n_clusters_per_class=2, scale=1.0,
                               random_state=20)

    # n_samples：指定样本数
    # n_features：指定特征数
    # n_classes：指定几分类
    # random_state：随机种子,使得随机状可重

    for x_, y_ in zip(X, y):
        print(y_, end=': ')
        print(x_)

def make_blob1():
   # 例子（生成三类数据用于聚类（100
   # 个样本,每个样本2个特征））：#
   from sklearn.datasets import make_blobs
   from matplotlib import pyplot

   data, label = make_blobs(n_samples=100, n_features=2, centers=5)

   # 绘制样本显示
   pyplot.scatter(data[:, 0], data[:, 1], c=label)
   pyplot.show()

   # 每个样本有几个属性或者特征
   n_features = 2

   data2, target = make_blobs(n_samples=100, n_features=3, centers=3, cluster_std=[1.0, 2.0, 3.0])
   # 在2D图中绘制样本,每个样本颜色不同
   pyplot.scatter(data2[:, 0], data2[:, 1], c=target)
   pyplot.show()

def make_class1():
   from matplotlib import pyplot
   x,y =  sklearn.datasets.make_classification(n_samples=100, n_features=20,
                                         n_informative=2, n_redundant=2, n_repeated=0, n_classes=2,
                                         n_clusters_per_class=2, weights=None, flip_y=0.01, class_sep=1.0,
                                         hypercube=True, shift=0.0, scale=1.0, shuffle=True, random_state=None)
   #　输入：　

   #n_features: 特征个数 = n_informative（） + n_redundant + n_repeated
   #n_informative：多信息特征的个数
   #n_redundant：冗余信息,informative特征的随机线性组合
   #n_repea#ted ：重复信息,随机提取n_informative和n_redundant
   #特征
   #n_classes：分类类别
   #n_clusters_per_class ：某一个类别是由几个cluster构成的
   pyplot.scatter(x[:, 0], x[:, 1])
   pyplot.show()

def make_gauss1():
    import matplotlib.pyplot as plt

    from sklearn.datasets import make_classification
    from sklearn.datasets import make_blobs
    from sklearn.datasets import make_gaussian_quantiles
    from sklearn.datasets import make_hastie_10_2

    plt.figure(figsize=(8, 8))
    plt.subplots_adjust(bottom=.05, top=.9, left=.05, right=.95)

    plt.subplot(421)
    plt.title("One informative feature, one cluster per class", fontsize='small')
    X1, Y1 = make_classification(n_samples=1000, n_features=2, n_redundant=0, n_informative=1,
                                 n_clusters_per_class=1)
    plt.scatter(X1[:, 0], X1[:, 1], marker='o', c=Y1)

    plt.subplot(422)
    plt.title("Two informative features, one cluster per class", fontsize='small')
    X1, Y1 = make_classification(n_samples=1000, n_features=2, n_redundant=0, n_informative=2,
                                 n_clusters_per_class=1)
    plt.scatter(X1[:, 0], X1[:, 1], marker='o', c=Y1)

    plt.subplot(423)
    plt.title("Two informative features, two clusters per class", fontsize='small')
    X2, Y2 = make_classification(n_samples=1000, n_features=2, n_redundant=0, n_informative=2)
    plt.scatter(X2[:, 0], X2[:, 1], marker='o', c=Y2)

    plt.subplot(424)
    plt.title("Multi-class, two informative features, one cluster",
              fontsize='small')
    X1, Y1 = make_classification(n_samples=1000, n_features=2, n_redundant=0, n_informative=2,
                                 n_clusters_per_class=1, n_classes=3)
    plt.scatter(X1[:, 0], X1[:, 1], marker='o', c=Y1)

    plt.subplot(425)
    plt.title("Three blobs", fontsize='small')
    X1, Y1 = make_blobs(n_samples=1000, n_features=2, centers=3)
    plt.scatter(X1[:, 0], X1[:, 1], marker='o', c=Y1)

    plt.subplot(426)
    plt.title("Gaussian divided into four quantiles", fontsize='small')
    X1, Y1 = make_gaussian_quantiles(n_samples=1000, n_features=2, n_classes=4)
    plt.scatter(X1[:, 0], X1[:, 1], marker='o', c=Y1)

    plt.subplot(427)
    plt.title("hastie data ", fontsize='small')
    X1, Y1 = make_hastie_10_2(n_samples=1000)
    plt.scatter(X1[:, 0], X1[:, 1], marker='o', c=Y1)
    plt.show()

def make_circ1():
    from sklearn.datasets import make_circles
    from sklearn.datasets import make_moons
    import matplotlib.pyplot as plt
    import numpy as np

    fig = plt.figure(1)
    x1, y1 = make_circles(n_samples=1000, factor=0.5, noise=0.1)
    plt.subplot(121)
    plt.title('make_circles function example')
    plt.scatter(x1[:, 0], x1[:, 1], marker='o', c=y1)

    plt.subplot(122)
    x1, y1 = make_moons(n_samples=1000, noise=0.1)
    plt.title('make_moons function example')
    plt.scatter(x1[:, 0], x1[:, 1], marker='o', c=y1)
    plt.show()
def test_plot():


    X = np.array([[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13], [14, 15], [16, 17], [18, 19]])
    print(X.shape)
    xx = X[ :,0]
    yy = X[1,:]
    plt.scatter(X[:, 0], X[:, 1]+1, marker='o')
    plt.show()


#2,数据预处理
#　　　数据预处理阶段是机器学习中不可缺少的一环,它会使得数据更加有效的被模型或者评估器识别。下面我们来看一下sklearn中有哪些平时我们常用的函数：
#1
#from sklearn import preprocessing
#　　为了使得训练数据的标准化规则与测试数据的标准化规则同步,preprocessing中提供了很多的Scaler：
#StandardScaler
#MaxAbsScaler
#MinMaxScaler
#RobustScaler
#Normalizer
#等其他预处理操作
#　　对应的有直接的函数使用：scale(),maxabs_scale(),minmax_scale(),robust_scale(),normaizer（）
#
#1
#sklearn.preprocessing.scale(X)
#make_circ1()
#StandardScaler计算训练集的平均值和标准差,以便测试数据及使用相同的变换。
#
#　　变换后各维特征有0均值,单位方差,也叫z-score规范化（零均值规范化）,计算方式是将特征值减去均值,除以标准差。
#
#fit
#
#　　用于计算训练数据的均值和方差,后面就会用均值和方差来转换训练数据
#
#fit_transform
#
#　　不仅计算训练数据的均值和方差,还会基于计算出来的均值和方差来转换训练数据,从而把数据转化成标准的正态分布。
#
#transform
#
#　　#很显然,它只是进行转换,只是把训练数据转换成标准的正态分布。（一般会把train和test集放在一起做标准化,
# #或者在train集上做标准化后,用同样的标准化器去标准化test集,此时可以使用scaler)。

def try_plot():
    data = np.array([[0, 0], [0, 0], [1, 10], [10, 1]])
    #plt.figure(figsize=(2, 2))
    #fig = plt.figure(2)


    plt.subplot(2,2,1)

    plt.scatter(data[:,0],data[:,1])
    # 1. 基于mean和std的标准化
    scaler = sklearn.preprocessing.StandardScaler().fit(data)
    print(scaler)

    x1 = scaler.transform(data)
    plt.subplot(2,2,2)
    plt.scatter(x1[:,0],x1[:,1],marker=',')
    # 2. 将每个特征值归一化到一个固定范围
    scaler2 = sklearn.preprocessing.MinMaxScaler(feature_range=(0, 1)).fit(x1)
    x2 = scaler2.transform(x1)
    plt.subplot(2,2,3)
    plt.scatter(x2[:,0],x2[:,1],c='r', marker='^')
    plt.show()

def try_model():
    sklearn.linear_model

def tenMin_sklearn():
    import sklearn.decomposition as sk_decomposition
    pca = sk_decomposition.PCA(n_components='mle', whiten=False, svd_solver='auto')
    iris = load_iris()
    # 特征变量
    iris_X = iris.data
    iris_y = iris.target
    pca.fit(iris_X)
    reduced_X = pca.transform(iris_X)  # reduced_X为降维后的数据
    print('PCA:')
    print('降维后的各主成分的方差值占总方差值的比例', pca.explained_variance_ratio_)
    print('降维后的各主成分的方差值', pca.explained_variance_)
    print('降维后的特征数', pca.n_components_)
#参数说明：
#n_components：指定希望PCA降维后的特征维度数目(>1), 指定主成分的方差和所占的最小比例阈值（0-1）,
# 'mle'用MLE算法根据特征的方差分布情况自己去选择一定数量的主成分特征来降维
#whiten： 判断是否进行白化。白化：降维后的数据的每个特征进行归一化,让方差都为1
#svd_solver：奇异值分解SVD的方法{‘auto’, ‘full’, ‘arpack’, ‘randomized’}

#LDA（线性评价分析）
#LDA基于费舍尔准则,即同一类样本尽可能聚合在一起,不同类样本应该尽量扩散；或者说,同雷洋被具有较好的聚合度,类别间具有较好的扩散度。
#既然涉及到了类别,那么LDA肯定是一个有监督算法,其实LDA既可以做特征提取液可以做分类。
#LDA具体的实现流程这里就不再赘述了,直接看skleran如何实现LDA。
    import sklearn.discriminant_analysis as sk_discriminant_analysis

    lda = sk_discriminant_analysis.LinearDiscriminantAnalysis(n_components=2)
    lda.fit(iris_X, iris_y)
    reduced_X = lda.transform(iris_X)  # reduced_X为降维后的数据
    print('LDA:')
    print('LDA的数据中心点:', lda.means_)  # 中心点
    print('LDA做分类时的正确率:', lda.score(X_test, y_test))  # score是指分类的正确率
    print('LDA降维后特征空间的类中心:', lda.scalings_)  # 降维后特征空间的类中心

iris = load_iris()
# 特征变量
iris_X = iris.data
iris_y = iris.target
X_train, X_test, y_train, y_test = train_test_split(iris_X, iris_y, test_size=0.3, random_state=42)

def linear_model1():
    import sklearn.linear_model as sk_linear


    model = sk_linear.LinearRegression(fit_intercept=True, normalize=False, copy_X=True, n_jobs=1)
    model.fit(X_train, y_train)
    acc = model.score(X_test, y_test)  # 返回预测的确定系数R2
    print('线性回归:')
    print('截距:', model.intercept_)  # 输出截距
    print('系数:', model.coef_)  # 输出系数
    print('线性回归模型评价:', acc)

def logistic1():

    #逻辑回归
    import sklearn.linear_model as sk_linear
    model = sk_linear.LogisticRegression(penalty='l2', dual=False, C=1.0, n_jobs=1, random_state=20, fit_intercept=True)
   #参数说明：
   #penalty：使用指定正则化项（默认：l2）
   #dual: n_samples > n_features取False（默认）
   #C：正则化强度的反,值越小正则化强度越大
   ##n_jobs: 指定线程数
   #random_state：随机数生成器
   #fit_intercept: 是否需要常量

    model.fit(X_train, y_train)  # 对模型进行训练
    acc = model.score(X_test, y_test)  # 根据给定数据与标签返回正确率的均值
    print('逻辑回归模型评价:', acc)

def MultinomialNB1():
    import sklearn.naive_bayes as sk_bayes
    model = sk_bayes.MultinomialNB(alpha=1.0, fit_prior=True, class_prior=None)  # 多项式分布的朴素贝叶斯
    model = sk_bayes.BernoulliNB(alpha=1.0, binarize=0.0, fit_prior=True, class_prior=None)  # 伯努利分布的朴素贝叶斯
    model = sk_bayes.GaussianNB()  # 高斯分布的朴素贝叶斯
    model.fit(X_train, y_train)
    acc = model.score(X_test, y_test)  # 根据给定数据与标签返回正确率的均值
    print( '朴素贝叶斯(高斯分布) 模型评价: ',acc)

def DecisionTreeClassifier1():
    #决策树是解决分类问题
    #criterion ：特征选择准则gini / entropy
    #max_depth：树的最大深度,None - 尽量下分
    #min_samples_split：分裂内部节点,所需要的最小样本树
    #min_samples_leaf：叶子节点所需要的最小样本数
    #max_features: 寻找最优分割点时的最大特征数
    #max_leaf_nodes：优先增长到最大叶子节点数
    #min_impurity_decrease：如果这种分离导致杂质的减少大于或等于这个值,则节点将被拆分。
#
    import sklearn.tree as sk_tree
    model = sk_tree.DecisionTreeClassifier(criterion='entropy', max_depth=None, min_samples_split=2, min_samples_leaf=1,
                                           max_features=None, max_leaf_nodes=None, min_impurity_decrease=0)
    model.fit(X_train, y_train)
    acc = model.score(X_test, y_test)  # 根据给定数据与标签返回正确率的均值
    print('决策树模型评价:', acc)


def SVC1():
    """SVM是常用的一种有监督的学习模型（即给你一些输入特征,告诉你这些特征的样本是属于A类,
    再给你一些输入特征,告诉你这些特征的样本是属于B类,现在再来一些数据,来判断它们是属于哪一类）。"""
    import sklearn.svm as sk_svm
    model = sk_svm.SVC(C=1.0, kernel='rbf', gamma='auto')
    model.fit(X_train, y_train)
    acc = model.score(X_test, y_test)  # 根据给定数据与标签返回正确率的均值
    print('SVM模型评价:', acc)

def MLP1():
    import sklearn.neural_network as sk_nn
    model = sk_nn.MLPClassifier(activation='tanh', solver='adam', alpha=0.0001, learning_rate='adaptive',
                                learning_rate_init=0.001, max_iter=200)
    model.fit(X_train, y_train)
    acc = model.score(X_test, y_test)  # 根据给定数据与标签返回正确率的均值
    print('神经网络模型评价:', acc)

#KNN（K-近邻算法）
def KNN1():
    import sklearn.neighbors as sk_neighbors
    import pickle
    # KNN分类
    model = sk_neighbors.KNeighborsClassifier(n_neighbors=5, n_jobs=1)
    model.fit(X_train, y_train)
    acc = model.score(X_test, y_test)  # 根据给定数据与标签返回正确率的均值
    print('KNN模型(分类)评价:', acc)

    # KNN回归
    model = sk_neighbors.KNeighborsRegressor(n_neighbors=5, n_jobs=1)
    model.fit(X_train, y_train)
    acc = model.score(X_test, y_test)  # 返回预测的确定系数R2
    print('KNN模型(回归)评价:', acc)

    import sklearn.model_selection as sk_model_selection
    accs = sk_model_selection.cross_val_score(model, iris_X, y=iris_y, scoring=None, cv=10, n_jobs=1)
    print('交叉验证结果:', accs)

    import sklearn.externals as sk_externals
    with open('clf.pickle', 'wb') as f:
        pickle.dump(model, f)
    #sk_externals.joblib.dump(model, 'model.pickle')  # 保存
   # model2 = sk_externals.joblib.load('model.pickle')  # 载入

KNN1()